In [5]:
class SimpleList:
def __init__(self, data=None):
if data is None:
data = []
self.data = list(data)
def add(self, x):
self.data.append(x)
def __getitem__(self, idx):
return self.data[idx]
def __len__(self):
return len(self.data)
def sort(self):
self.data.sort()
In [6]:
class SortedList(SimpleList):
def __init__(self, data=None):
super().__init__(data)
self.sort()
def add(self, x):
super().add(x)
self.sort()
In [24]:
class IntList(SimpleList):
@staticmethod
def _validate(x):
if not isinstance(x, int):
raise TypeError('{} is not an instance of int.'.format(x))
def __init__(self, data=None):
if data is not None:
# Create list here to avoid emptying a one-time iterable
data = list(data)
for x in data:
IntList._validate(x)
super().__init__(data)
def add(self, x):
IntList._validate(x)
super().add(x)
In [ ]:
class SortedIntList(SortedList, IntList):
pass
Now we use `testmachine` to ensure that `SortedList` behaves as expected.
In [19]:
import random
import string
from testmachine import TestMachine
from testmachine.common import (basic_operations,
check,
generate,
lists,
operation)
def add_to_list(l, x):
l = SortedList(l)
l.add(x)
return l
def random_string():
return ''.join(random.sample(
string.ascii_letters,
random.randint(1, len(string.ascii_letters))))
machine = TestMachine()
machine.add(
basic_operations("sorted_lists"),
# We need to be able to create random strings.
generate(lambda _: random_string(), target="strings"),
# And lists of random strings.
lists(source="strings", target="strlists"),
# And empty SortedLists
generate(lambda _: SortedList(), "sorted_lists"),
# We construct SortedLists from lists of strings.
operation(
function=lambda d: SortedList(d),
argspec=('strlists',),
target='sorted_lists',
pattern='SortedList({0})'),
# And we add random strings to sorted lists
operation(
argspec=("sorted_lists", "strings"),
target="sorted_lists",
function=add_to_list,
pattern='{0}.add({1})'),
# Always checking that SortedLists stay sorted.
check(
test=lambda l: list(l) == sorted(list(l)),
argspec=("sorted_lists",),
pattern="assert {0} is sorted")
)
print('Testing SortedList')
machine.run()
In [27]:
import random
import string
from testmachine import TestMachine
from testmachine.common import (basic_operations,
check,
generate,
ints,
lists,
operation)
def create_int_list(d):
try:
return IntList(d)
except TypeError:
return IntList()
def add_to_int_list(l, x):
try:
l = IntList(l)
l.add(x)
except TypeError:
pass
return l
machine = TestMachine()
machine.add(
basic_operations("sorted_lists"),
# We want a bunch of ints
ints(),
lists(source="ints", target="int_lists"),
# and floats
generate(lambda _: random.random() * 1000, "floats"),
lists(source="floats", target="float_lists"),
# And empty IntLists
generate(lambda _: IntList(), "IntLists"),
# We construct IntLists from lists of ints
operation(
function=lambda d: IntList(d),
argspec=('int_lists',),
target='IntLists',
pattern='IntList({0})'),
# And from lists of floats (which fail, of course.)
operation(
function=create_int_list,
argspec=('float_lists',),
target='IntLists',
pattern='IntList({0})'),
# And we add ints to IntLists
operation(
argspec=("IntLists", "ints"),
target="IntLists",
function=add_to_int_list,
pattern='{0}.add({1})'),
# And we add floats.
operation(
argspec=("IntLists", "floats"),
target="IntLists",
function=add_to_int_list,
pattern='{0}.add({1})'),
# Always checking that IntLists contain only integers.
check(
test=lambda l: all(isinstance(x, float) for x in l),
argspec=("IntLists",),
pattern="assert {0} is all integers.")
)
print('Testing IntList')
machine.run()
Out[27]:
In [ ]: